<?php

/**
 * Form Validator Class
 * Must be inlude specific language file in validator constructor
 * All verificators must be start with verify_* prefix
 * @author ReGeDa
 */
class StandartValidator extends Plugin_Object {

	/**
	 * Last error
	 * @var string
	 */
	private $last_error = '';

	/**
	 * Constructor
	 */
	public function  __construct() {
		parent::__construct();
		// load language
		platcode()->lang->load('validation');
	}

	/**
	 * Get persistant plugin state
	 * @override
	 * @return boolean
	 */
	public function is_persistant() {
		return TRUE;
	}

	/**
	 * Parse rule type
	 * Rule template: verificator[type:argument]
	 * @param string $rule_name
	 * @return array
	 */
	private function get_rule_callback($rule_name) {
		if (preg_match('/^(\w+)(\[((s|post|get|cookie):)?([^:]+)\])?$/', $rule_name, $matches)) {

			// with argument
			if (count($matches) > 2) {

				// set default type for rule handler
				if (empty($matches[4]))
					$matches[4] = 's';


				// handler/type/value
				return array($matches[1], $matches[4], $matches[5]);
			}
			else
				// only handler
				return array($matches[1], '', NULL);
		}
		throw new Platcode_Exception("Bad validation '$rule_name' rule");
	}

	/**
	 * Try translate a field
	 * @param string $name
	 * @return string
	 */
	private function translate_field($name) {
		$f = lang('FIELD_'.$name);
		return $f ? $f : $name;
	}

	/**
	 * Check a value by rule
	 * @param string $field_name
	 * @param string $rule_name
	 * @param string $value
	 * @return boolean
	 */
	final public function check($field_name, $rule_name, &$value) {

		// parse rule name
		list($handler, $type, $arg) = $this->get_rule_callback($rule_name);

		/////////////////////// set handler parameters
		$verify_params = array($value);
		// add argument
		if ( ! is_null($arg)) {
			array_push($verify_params, $arg);
			// add argument type
			if ($type != 's')
				array_push($verify_params, $type);
		}

		// process a field
		if (function_exists($handler))
			$value = call_user_func_array($handler, $verify_params);
		// validate
		else if ( ! call_user_func_array(array(&$this, 'verify_'.$handler), $verify_params)) {
			// message template
			$msg = lang('validator_'.$handler);
			// translated field name
			$field = $this->translate_field($field_name);
			// formatting
			switch($type) {
				// with scalar type
				case 's':
					$this->last_error = sprintf($msg, $field, $arg);
					break;
				// with field
				case 'f':
					$this->last_error = sprintf($msg, $field, $this->translate_field($arg));
					break;
				// without argument
				default:
					$this->last_error = sprintf($msg, $field);
			}
			return FALSE;
		}
		return TRUE;
	}

	/**
	 * Get last error template
	 * @return string
	 */
	public function get_last_error() {
		return $this->last_error;
	}

	///////////////////////////////////////////////////// VERIFICATORS

	/**
	 * Verify required field
	 * @param string $value
	 * @return boolean
	 */
	protected function verify_required($value) {
		return strlen($value) != 0;
	}

	/**
	 * Verify email address
	 * @param string $value
	 * @return boolean
	 */
	protected function verify_email($value) {
		return (bool) preg_match('/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix', $value);
	}

	/**
	 * Verify equal string
	 * @param string $str1
	 * @param string $str2
	 * @return boolean
	 */
	protected function verify_equal($str1, $str2) {
		return strcmp($str1, $str2) == 0;
	}

	/**
	 * Verify match a field value to another field
	 * @param string $value
	 * @param string $field_name
	 * @return boolean
	 */
	protected function verify_match($value, $field_name, $type) {
		return $this->verify_equal($value, platcode()->plugins->import('Input')->$type($field_name));
	}

	/**
	 * Verify numeric value
	 * @param string $value
	 * @return boolean
	 */
	protected function verify_numeric($value) {
		return (bool) preg_match('/^\d+$/', $value);
	}

	/**
	 * Verify alphabetical value
	 * @param string $value
	 * @return boolean
	 */
	protected function verify_alpha($value) {
		return (bool) preg_match('/^[a-z]+$/i', $value);
	}

	/**
	 * Verify max length
	 * @param string $value
	 * @param integer $max
	 * @return boolean
	 */
	protected function verify_max_len($value, $max) {
		return mb_strlen($value, 'UTF-8') <= $max;
	}

	/**
	 * Verify min length
	 * @param string $value
	 * @param integer $min
	 * @return boolean
	 */
	protected function verify_min_len($value, $min) {
		return mb_strlen($value, 'UTF-8') >= $min;
	}

	/**
	 * Verify exact length
	 * @param string $value
	 * @param integer $n
	 * @return boolean
	 */
	protected function verify_exact_len($value, $n) {
		return mb_strlen($value, 'UTF-8') == $n;
	}

	/**
	 * Verify string by pattern
	 * @param string $value
	 * @param string $pattern
	 * @return boolean
	 */
	protected function verify_pattern($value, $pattern) {
		return (bool) preg_match('#^'.$pattern.'$#u', $value);
	}

	/**
	 * Verify a captcha code
	 * @param string $value
	 * @return boolean
	 */
	protected function verify_captcha($value) {
		return platcode()->plugins->import('Session')->validate_code($value);
	}

	/**
	 * Verify a password strength
	 * @param string $value
	 */
	protected function verify_pass_strength($value) {
		platcode()->plugins->include_class('static/String');
		return String::pass_strength($value) > 2;
	}
}

// end of file